/* 
store 仓库对象的 3 的 API：
  store.getState()             -  获取仓库状态
  store.dispatch(action)       -  修改仓库数据(仓库行为)
  store.subscribe(listener)    -  订阅通知
*/

import React from 'react';
import { createStore } from 'redux';

// 仓库默认状态
const defaultState = { num: 0 };
// 仓库管理员
const reducer = (state = defaultState, action) => {
  // 根据 action 对象修改仓库数据
  if (action.type === 'add') {
    let newState = JSON.parse(JSON.stringify(state));  // 深拷贝
    newState.num += action.value;
    return newState;
  }
  // 如果没有传 action 就直接返回
  return state;
};
// 创建仓库并丢进去一个管理员
const store = createStore(reducer);

// 购物车数量组件
class CartCount extends React.Component {
  state = {
    // 解构仓库状态到组件状态中
    ...store.getState()
  };
  // 组件挂载完毕的时候 - 订阅仓库状态更新
  componentDidMount() {
    // 订阅 ->   仓库的状态发生了改变，自动通知执行所有 store.subscribe() 方法
    // 把更新的组件的操作封装成一个方法
    const listener = () => {
      this.setState({ num: store.getState().num });
    };
    // 订阅函数执行后，会返回一个用于取消订阅的函数
    this.unSubscribeFn = store.subscribe(listener);
  }
  // 组件卸载时，取消订阅
  componentWillUnmount() {
    // 调用取消订阅的函数
    this.unSubscribeFn();
  }
  // 渲染
  render() {
    return (
      <h1>头部购物车数量展示：{this.state.num}</h1>
    );
  }
}

class App extends React.Component {
  state = {
    // 1. 从仓库拿到的数据，解构添加到了 state 中
    ...store.getState(),
    show: true
  };
  addToCart = () => {
    // action 其实就是个对象 - 告诉管理员如何操作数据
    const action = {
      type: 'add',
      value: 1
    };
    // 向仓库发送 action 动作  ->  自动触发管理员的函数 reducer
    store.dispatch(action);

    // 拿到仓库数据，更新视图
    this.setState({ num: store.getState().num });
  };
  render() {
    return (
      <div className="App">
        {/* 条件渲染 */}
        {this.state.show && <CartCount></CartCount>}
        <hr />
        <hr />
        {/* 点击更新 show 数据 */}
        <button onClick={() => this.setState({ show: !this.state.show })}>显示或隐藏组件</button>
        <h1>从仓库中拿到的数据展示到首页：{this.state.num}</h1>
        <button onClick={this.addToCart}>加入购物车</button>
      </div>
    );
  }
}

export default App;
